package com.ztc.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

/**
 * @类名：FtpUtil.java
 * @作者：李晓平
 * @时间：2018年6月30日 下午4:18:35
 * @描述：ftp工具类
 */
public class FtpUtil {
	// ftp服务器地址
	public String hostname = GlobalUtil.getGlobalParam("ftp.host");
	// ftp登录账号
	public String username = GlobalUtil.getGlobalParam("ftp.username");
	// ftp登录密码
	public String password = GlobalUtil.getGlobalParam("ftp.password");
	// ftp服务器端口号默认为21
	public int port = GlobalUtil.getGlobalParamByInt("ftp.port");
	// ftp默认存储路径
	public String path = GlobalUtil.getGlobalParam("ftp.path");

	public FTPClient ftpClient = null;

	/**
	 * 初始化ftp服务器
	 */
	public void initFtpClient() {
		ftpClient = new FTPClient();
		ftpClient.setControlEncoding("utf-8");
		try {
			System.out.println("connecting...ftp server:" + this.hostname + ":" + this.port);
			ftpClient.connect(hostname, port); // 连接ftp服务器
			ftpClient.login(username, password); // 登录ftp服务器
//			ftpClient.enterLocalActiveMode();//主动模式
			ftpClient.enterLocalPassiveMode();//被动模式
			int replyCode = ftpClient.getReplyCode(); // 是否成功登录服务器
			if (!FTPReply.isPositiveCompletion(replyCode)) {
				System.out.println("connect failed...ftp server:" + this.hostname + ":" + this.port);
			}
			ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE);
	        ftpClient.changeWorkingDirectory(path);
			System.out.println("connect successful...ftp server:" + this.hostname + ":" + this.port);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 上传文件
	 * 
	 * @param pathname
	 *            ftp服务保存地址
	 * @param fileName
	 *            上传到ftp的文件名
	 * @param originfilename
	 *            待上传文件的名称（绝对地址） *
	 * @return
	 */
	public boolean uploadFile(String filePath, String originfilename) {
		boolean flag = false;
		InputStream inputStream = null;
		try {
			System.out.println("start upload file");
			String pathname = "";
			String fileName = "";
			if(filePath.contains("/")) {
				pathname = filePath.substring(0, filePath.lastIndexOf("/"));
				fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
			} else {
				fileName = filePath;
			}
			inputStream = new FileInputStream(new File(originfilename));
			initFtpClient();
			CreateDirecroty(pathname);
//			ftpClient.makeDirectory(pathname);
//			ftpClient.changeWorkingDirectory(pathname);
			boolean result = ftpClient.storeFile(fileName, inputStream);
			if(result) {
				System.out.println("upload file success");
			} else {
				System.out.println("upload file fail");
			}
			inputStream.close();
			ftpClient.logout();
			flag = true;
//			System.out.println("upload file success");
		} catch (Exception e) {
			System.out.println("upload file fail");
			e.printStackTrace();
			flag = false;
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (null != inputStream) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

	/**
	 * 上传文件
	 * 
	 * @param pathname
	 *            ftp服务保存地址
	 * @param fileName
	 *            上传到ftp的文件名
	 * @param inputStream
	 *            输入文件流
	 * @return
	 */
	public boolean uploadFile(String filePath, InputStream inputStream) {
		boolean flag = false;
		try {
			System.out.println("start upload file");
			String pathname = "";
			String fileName = "";
			if(filePath.contains("/")) {
				pathname = filePath.substring(0, filePath.lastIndexOf("/"));
				fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
			} else {
				fileName = filePath;
			}
			initFtpClient();
			CreateDirecroty(pathname);
//			ftpClient.makeDirectory(pathname);
//			ftpClient.changeWorkingDirectory(pathname);
			boolean result = ftpClient.storeFile(fileName, inputStream);
			if(result) {
				System.out.println("upload file success");
			} else {
				System.out.println("upload file fail");
			}
			inputStream.close();
			ftpClient.logout();
			flag = true;
//			System.out.println("upload file success");
		} catch (Exception e) {
			System.out.println("upload file fail");
			e.printStackTrace();
			flag = false;
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (null != inputStream) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

	// 改变目录路径
	public boolean changeWorkingDirectory(String directory) {
		boolean flag = true;
		try {
			flag = ftpClient.changeWorkingDirectory(directory);
			if (flag) {
				System.out.println("enter directory " + directory + " success！");

			} else {
				System.out.println("enter directory " + directory + " fail！start create directory");
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		return flag;
	}

	// 创建多层目录文件，如果有ftp服务器已存在该文件，则不创建，如果无，则创建
	public boolean CreateDirecroty(String remote) throws IOException {
		boolean success = true;
		if(StringUtils.isBlank(remote)) {
			return success;
		}
		String directory = remote + "/";
		// 如果远程目录不存在，则递归创建远程服务器目录
		if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory))) {
			int start = 0;
			int end = 0;
			if (directory.startsWith("/")) {
				start = 1;
			} else {
				start = 0;
			}
			end = directory.indexOf("/", start);
			String path = "";
			String paths = "";
			while (true) {
				String subDirectory = new String(remote.substring(start, end).getBytes("GBK"),
						"iso-8859-1");
				path = path + "/" + subDirectory;
				if (!existFile(path)) {
					if (makeDirectory(subDirectory)) {
						changeWorkingDirectory(subDirectory);
					} else {
						System.out.println("create directory[" + subDirectory + "]fail");
						changeWorkingDirectory(subDirectory);
					}
				} else {
					changeWorkingDirectory(subDirectory);
				}

				paths = paths + "/" + subDirectory;
				start = end + 1;
				end = directory.indexOf("/", start);
				// 检查所有目录是否创建完毕
				if (end <= start) {
					break;
				}
			}
		}
		return success;
	}

	// 判断ftp服务器文件是否存在
	public boolean existFile(String path) throws IOException {
		boolean flag = false;
		FTPFile[] ftpFileArr = ftpClient.listFiles(path);
		if (ftpFileArr.length > 0) {
			flag = true;
		}
		return flag;
	}

	// 创建目录
	public boolean makeDirectory(String dir) {
		boolean flag = true;
		try {
			flag = ftpClient.makeDirectory(dir);
			if (flag) {
				System.out.println("create directory " + dir + " success!");

			} else {
				System.out.println("create directory " + dir + " fail!");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * * 下载文件 *
	 * 
	 * @param pathname
	 *            FTP服务器文件目录 *
	 * @param filename
	 *            文件名称 *
	 * @param localpath
	 *            下载后的文件路径 *
	 * @return
	 */
	public boolean downloadFile(String filePath, String localpath) {
		boolean flag = false;
		OutputStream os = null;
		try {
			System.out.println("开始下载文件");
			String pathname = "";
			String fileName = "";
			if(filePath.contains("/")) {
				pathname = filePath.substring(0, filePath.lastIndexOf("/"));
				fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
			} else {
				fileName = filePath;
			}
			initFtpClient();
			// 切换FTP目录
			ftpClient.changeWorkingDirectory(pathname);
			FTPFile[] ftpFiles = ftpClient.listFiles();
			for (FTPFile file : ftpFiles) {
				if (fileName.equalsIgnoreCase(file.getName())) {
					File localFile = new File(localpath + "/" + file.getName());
					os = new FileOutputStream(localFile);
					ftpClient.retrieveFile(file.getName(), os);
					os.close();
				}
			}
			ftpClient.logout();
			flag = true;
			System.out.println("下载文件成功");
		} catch (Exception e) {
			System.out.println("下载文件失败");
			e.printStackTrace();
			flag = false;
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (null != os) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

	/**
	 * * 删除文件 *
	 * 
	 * @param pathname
	 *            FTP服务器保存目录 *
	 * @param filename
	 *            要删除的文件名称 *
	 * @return
	 */
	public boolean deleteFile(String pathname, String filename) {
		boolean flag = false;
		try {
			System.out.println("开始删除文件");
			initFtpClient();
			// 切换FTP目录
			ftpClient.changeWorkingDirectory(pathname);
			ftpClient.dele(filename);
			ftpClient.logout();
			flag = true;
			System.out.println("删除文件成功");
		} catch (Exception e) {
			System.out.println("删除文件失败");
			e.printStackTrace();
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}
	
	/**
	 * 遍历文件
	 * @param pathName
	 */
	public List<String> listFiles(String pathName, String[] exts) throws Exception{
		List<String> arFiles = new ArrayList<String>();
		try {
			System.out.println("start list file");
			initFtpClient();
			listFiles(pathName, exts, arFiles);
			ftpClient.logout();
			System.out.println("list file success");
		} catch (Exception e) {
			System.out.println("list file fail");
			e.printStackTrace();
			throw e;
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return arFiles;
	}
	
	/**
     * 递归遍历出目录下面所有文件
     *
     * @param pathName 需要遍历的目录，必须以"/"开始和结束
     * @throws IOException
     */
    public void listFiles(String pathName, List<String> arFiles) throws IOException {
    	//更换目录到当前目录
    	if(!pathName.equals("/")) {
    		changeWorkingDirectory(pathName);
    	}
        FTPFile[] files = ftpClient.listFiles();
        for (FTPFile file : files) {
            if (file.isFile()) {
                arFiles.add(pathName + file.getName());
            } else if (file.isDirectory()) {
                // 需要加此判断。否则，ftp默认将‘项目文件所在目录之下的目录（./）’与‘项目文件所在目录向上一级目录下的目录（../）’都纳入递归，这样下去就陷入一个死循环了。需将其过滤掉。
                if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
                	listFiles(file.getName() + "/", arFiles);
                }
            }
        }
    }

    /**
     * 递归遍历目录下面指定的文件名
     *
     * @param pathName 需要遍历的目录，必须以"/"开始和结束
     * @param ext      文件的扩展名
     * @throws IOException
     */
    public void listFiles(String pathName, String[] exts, List<String> arFiles) throws IOException {
    	//更换目录到当前目录
    	if(!pathName.equals("/")) {
    		boolean flag = changeWorkingDirectory(pathName);
    		if(!flag) {
        		ftpClient.changeToParentDirectory();
        		changeWorkingDirectory(pathName);
    		}
    	}
        FTPFile[] files = ftpClient.listFiles();
        for (FTPFile file : files) {
            if (file.isFile()) {
            	for(String ext : exts) {
                    if (file.getName().endsWith(ext)) {
                    	if(pathName.startsWith("/")) {
                            arFiles.add(pathName + file.getName());
                    	} else {
                            arFiles.add("/" + pathName + file.getName());
                    	}
                        break;
                    }
            	}
            } else if (file.isDirectory()) {
                if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
                	listFiles(file.getName() + "/", exts, arFiles);
                }
            }
        }
    }

	public static void main(String[] args) {
		FtpUtil ftp = new FtpUtil();
		// ftp.uploadFile("ftpFile/data/123.docx", "E://123.docx");
		// ftp.downloadFile("ftpFile/data/123.docx", "F://");
		ftp.deleteFile("ftpFile/data", "123.docx");
		System.out.println("ok");
	}
}
